package cdms.web;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import java.util.Date;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import cdms.db.DeliveryOrderRepository;
import cdms.db.ManagerRepository;
import cdms.db.SenderRepository;
import cdms.domain.DeliveryOrder;
import cdms.domain.Manager;
import cdms.domain.Sender;
import cdms.util.SnowFlake;

/**
 * Manager controller
 * 
 * @author chenjing
 * @version v1.0
 */
@Controller
@RequestMapping("/manager")
public class ManagerController {

	@Autowired
	private ManagerRepository managerRepository;

	@Autowired
	private SenderRepository senderRepository;

	@Autowired
	private DeliveryOrderRepository deliveryOrderRepository;

	private static final SnowFlake SNOW_FLAKE = new SnowFlake(2, 3);

	/**
	 * manager login
	 * 
	 * @return
	 */
	@RequestMapping(value = "/login", method = GET)
	public String showManagerLoginForm(HttpServletRequest request, Model model) {
		Cookie cookies[] = request.getCookies();
		if (cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				if (cookies[i].getName().equals("managerUserName")) {
					model.addAttribute("managerUserName", cookies[i].getValue());
					break;
				}
			}
		}
		return "manager/managerLoginForm";
	}

	/**
	 * login request
	 * 
	 * @param userName
	 * @param password
	 * @param session
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/login", method = POST)
	public String processManagerLogin(@RequestParam(value = "userName", defaultValue = "") String userName,
			@RequestParam(value = "password", defaultValue = "") String password, HttpSession session, Model model,
			HttpServletResponse response) {
		session.removeAttribute("sender");
		session.removeAttribute("manager");
		Manager manager = managerRepository.findByUserName(userName, password);
		if (manager != null && manager.isDelete() == false) {
			Cookie cookie = new Cookie("managerUserName", userName);
			cookie.setMaxAge(30 * 24 * 60 * 60);
			response.addCookie(cookie);
			session.setAttribute("manager", manager);
			return "redirect:/";
		} else {
			model.addAttribute("msg", "用户名或密码错误！");
			return "manager/managerLoginForm";
		}

	}

	/**
	 * 注销
	 * 
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/logout", method = GET)
	public String logout(HttpSession session) {
		session.removeAttribute("manager");
		session.invalidate();
		return "redirect:/";
	}

	/**
	 * Manager list
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	@RequestMapping(value = "/managers", method = RequestMethod.GET)
	public PaginationSupport<Manager> managers(@RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
			@RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {

		return managerRepository.findPage(pageNo, pageSize);
	}

	/**
	 * Sender list
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	@RequestMapping(value = "/senders", method = RequestMethod.GET)
	public PaginationSupport<Sender> senders(@RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
			@RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {

		return senderRepository.findPage(pageNo, pageSize);
	}

	/**
	 * DeliveryOrder list
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	@RequestMapping(value = "/orders", method = RequestMethod.GET)
	public String orders(@RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
			@RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
			@RequestParam(value = "state", defaultValue = "-1") int state, Model model) {
		PaginationSupport<DeliveryOrder> paginationSupport = null;
		if (state == 0 || state == 1 || state == 2) {
			paginationSupport = deliveryOrderRepository.statePage(pageNo, pageSize, state);
		} else {
			state = -1;
			paginationSupport = deliveryOrderRepository.findPage(pageNo, pageSize);
		}
		model.addAttribute("state", state);
		model.addAttribute("paginationSupport", paginationSupport);
		return "manager/orders";
	}

	/**
	 * Manager information
	 * 
	 * @param model
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/profile", method = GET)
	public String showManagerProfile(Model model, HttpSession session) {
		Manager manager = (Manager) session.getAttribute("manager");
		if (manager != null) {
			model.addAttribute(manager);
			return "manager/profile";
		} else {
			return "redirect:/";
		}
	}

	/**
	 * change manager's profile and update the session
	 * 
	 * @param manager
	 * @param errors
	 * @param model
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/changeProfile", method = POST)
	public String changeProfile(@Valid Manager manager, Errors errors, Model model, HttpSession session) {
		if (errors.getErrorCount() > 1) {
			return "manager/profile";
		}
		manager.setPassword(null);
		manager = managerRepository.update(manager);
		session.setAttribute("manager", manager);
		model.addAttribute("msg", "修改成功！");
		return "manager/profile";
	}

	/**
	 * enter the page of changePassword
	 */
	@RequestMapping(value = "/changePassword", method = GET)
	public String changePassword() {
		return "manager/changePassword";
	}

	/**
	 * change manager's password
	 * 
	 * @param manager
	 * @param errors
	 * @param model
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/changePassword", method = POST)
	public String changePassword(@RequestParam(value = "oldPassword") String oldPassword,
			@RequestParam(value = "newPassword1") String newPassword1,
			@RequestParam(value = "newPassword2") String newPassword2, Model model, HttpSession session) {
		Manager manager = (Manager) session.getAttribute("manager");
		manager = managerRepository.findByUserName(manager.getUserName(), oldPassword);
		if (manager != null) {
			if (newPassword1.equals(newPassword2)) {
				if (newPassword1.length() >= 5 && newPassword1.length() <= 25) {
					manager.setPassword(newPassword1);
					managerRepository.update(manager);
					model.addAttribute("msg", "修改成功！");
				} else {
					// newPassword not in a correct format
					model.addAttribute("msg", "新密码格式错误");
				}
			} else {
				// newPassword is not equal
				model.addAttribute("msg", "两次密码不一致");
			}
		} else {
			// oldPassword is not correct
			model.addAttribute("msg", "原密码错误");
		}
		return "manager/changePassword";
	}

	/**
	 * add a manager
	 * 
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/addManager", method = GET)
	public String addManager(Model model) {
		model.addAttribute(new Manager());
		return "manager/addManager";
	}

	/**
	 * add a manager
	 * 
	 * @param manager
	 * @param errors
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/addManager", method = POST)
	public String addManager(@Valid Manager manager, Errors errors, Model model) {
		if (errors.hasErrors()) {
			return "manager/addManager";
		}
		Manager temp = managerRepository.findByUserName(manager.getUserName());
		if (temp == null) {
			manager.setDelete(false);
			manager = managerRepository.save(manager);
			return "redirect:/manager/managers";
		} else {
			model.addAttribute("msg", "该用户名已存在！");
			return "manager/addManager";
		}
	}

	/**
	 * delete a manager
	 * 
	 * @param id
	 * @param model
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/deleteManager/{id}", method = GET)
	public String deleteManager(@PathVariable Long id, Model model, HttpSession session) {
		Manager manager = (Manager) session.getAttribute("manager");
		if (manager.getId() != id)
			managerRepository.delete(id);
		return "redirect:/manager/managers";
	}

	/**
	 * change manager's information
	 * 
	 * @param id
	 * @param model
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/managerInformation/{id}", method = GET)
	public String changeManagerInformation(@PathVariable Long id, Model model, HttpSession session) {
		Manager manager = (Manager) session.getAttribute("manager");
		Manager managerToChange = managerRepository.findOne(id);
		if (manager.getId() != id) {
			model.addAttribute("manager", managerToChange);
			return "manager/managerInformation";
		}
		return "redirect:/manager/managers";
	}

	/**
	 * change manager's information
	 * 
	 * @param manager
	 * @param errors
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/managerInformation/change", method = POST)
	public String changeManagerInformation(@Valid Manager manager, Errors errors, Model model) {
		if (manager.getPassword().equals("")) {
			if (errors.getErrorCount() > 1) {
				return "manager/managerInformation";
			}
			manager.setPassword(null);
			manager = managerRepository.update(manager);
			model.addAttribute("msg", "修改成功！");
		} else {
			if (errors.hasErrors()) {
				return "manager/managerInformation";
			}
			managerRepository.update(manager);
			manager.setPassword(null);
			managerRepository.update(manager);
			model.addAttribute("msg", "修改成功！");
		}
		model.addAttribute("manager", manager);
		return "manager/managerInformation";
	}

	/**
	 * search managers by fullName or userName
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @param type
	 * @param search
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/managerSearch", method = RequestMethod.POST)
	public String searchManagersPOST(@RequestParam(value = "type") String type,
			@RequestParam(value = "search") String search, Model model) {
		PaginationSupport<Manager> paginationSupport;
		if (type.equals("userName")) {
			paginationSupport = managerRepository.searchByUserName(1, 10, search);
		} else {
			paginationSupport = managerRepository.searchByFullName(1, 10, search);
		}
		model.addAttribute("search", search);
		model.addAttribute("type", type);
		model.addAttribute("paginationSupport", paginationSupport);
		return "manager/managers";
	}

	/**
	 * search managers by fullName or userName
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @param type
	 * @param search
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/managerSearch", method = RequestMethod.GET)
	public String searchManagersGET(@RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
			@RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
			@RequestParam(value = "type") String type, @RequestParam(value = "search") String search, Model model) {
		PaginationSupport<Manager> paginationSupport;
		if (type.equals("userName")) {
			paginationSupport = managerRepository.searchByUserName(pageNo, pageSize, search);
		} else {
			paginationSupport = managerRepository.searchByFullName(pageNo, pageSize, search);
		}
		model.addAttribute("search", search);
		model.addAttribute("type", type);
		model.addAttribute("paginationSupport", paginationSupport);
		return "manager/managers";
	}

	/**
	 * add a sender
	 * 
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/addSender", method = GET)
	public String addSender(Model model) {
		model.addAttribute(new Sender());
		return "manager/addSender";
	}

	/**
	 * add a sender
	 * 
	 * @param sender
	 * @param errors
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/addSender", method = POST)
	public String addSender(@Valid Sender sender, Errors errors, Model model) {
		if (errors.hasErrors()) {
			return "manager/addSender";
		}
		Sender temp = senderRepository.findOneByUserName(sender.getUserName());
		if (temp == null) {
			sender.setDelete(false);
			senderRepository.save(sender);
			return "redirect:/manager/senders";
		} else {
			model.addAttribute("msg", "该用户名已存在！");
			return "manager/addSender";
		}
	}

	/**
	 * delete a sender
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/deleteSender/{id}", method = GET)
	public String deleteSender(@PathVariable Long id) {
		senderRepository.delete(id);
		return "redirect:/manager/senders";
	}

	/**
	 * change sender's information
	 * 
	 * @param id
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/senderInformation/{id}", method = GET)
	public String changeSenderInformation(@PathVariable Long id, Model model) {
		Sender sender = senderRepository.findOneById(id);
		model.addAttribute("sender", sender);
		return "manager/senderInformation";
	}

	/**
	 * change sender's information
	 * 
	 * @param sender
	 * @param errors
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/senderInformation/change", method = POST)
	public String changeSenderInformation(@Valid Sender sender, Errors errors, Model model) {
		if (sender.getPassword().equals("")) {
			if (errors.getErrorCount() > 1) {
				return "manager/senderInformation";
			}
			sender.setPassword(null);
			sender = senderRepository.update(sender);
			model.addAttribute("msg", "修改成功！");
		} else {
			if (errors.hasErrors()) {
				return "manager/senderInformation";
			}
			senderRepository.update(sender);
			sender.setPassword(null);
			senderRepository.update(sender);
			model.addAttribute("msg", "修改成功！");
		}
		model.addAttribute("sender", sender);
		return "manager/senderInformation";
	}

	/**
	 * search senders by fullName or userName
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @param type
	 * @param search
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/senderSearch", method = RequestMethod.POST)
	public String searchSendersPOST(@RequestParam(value = "type") String type,
			@RequestParam(value = "search") String search, Model model) {
		PaginationSupport<Sender> paginationSupport;
		if (type.equals("userName")) {
			paginationSupport = senderRepository.searchByUserName(1, 10, search);
		} else {
			paginationSupport = senderRepository.searchByFullName(1, 10, search);
		}
		model.addAttribute("search", search);
		model.addAttribute("type", type);
		model.addAttribute("paginationSupport", paginationSupport);
		return "manager/senders";
	}

	/**
	 * search senders by fullName or userName
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @param type
	 * @param search
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/senderSearch", method = RequestMethod.GET)
	public String searchSendersGET(@RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
			@RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
			@RequestParam(value = "type") String type, @RequestParam(value = "search") String search, Model model) {
		PaginationSupport<Sender> paginationSupport;
		if (type.equals("userName")) {
			paginationSupport = senderRepository.searchByUserName(pageNo, pageSize, search);
		} else {
			paginationSupport = senderRepository.searchByFullName(pageNo, pageSize, search);
		}
		model.addAttribute("search", search);
		model.addAttribute("type", type);
		model.addAttribute("paginationSupport", paginationSupport);
		return "manager/senders";
	}

	/**
	 * add a order
	 * 
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/addOrder", method = GET)
	public String addOrder(Model model) {
		DeliveryOrder deliveryOrder = new DeliveryOrder();
		deliveryOrder.setCost(null);
		model.addAttribute("deliveryOrder", deliveryOrder);
		return "manager/addOrder";
	}

	/**
	 * add a order
	 * 
	 * @param deliveryOrder
	 * @param errors
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/addOrder", method = POST)
	public String addOrder(@Valid DeliveryOrder deliveryOrder, Errors errors, Model model, HttpSession session) {
		if (errors.hasErrors()) {
			return "manager/addOrder";
		}
		if (deliveryOrder.getCost() <= 0.0 || deliveryOrder.getCost() > 999.9999) {
			model.addAttribute("msg", "配送费用不合理,合理范围：0.00~999.99");
			return "manager/addOrder";
		}
		Manager manager = (Manager) session.getAttribute("manager");
		deliveryOrderRepository.save(new DeliveryOrder(null, String.valueOf(SNOW_FLAKE.nextId()), manager,
				deliveryOrder.getDeliverAddress(), deliveryOrder.getDeliverPhone(), deliveryOrder.getReceiveAddress(),
				deliveryOrder.getReceivePhone(), deliveryOrder.getCost(), new Date()));
		return "redirect:/manager/orders";
	}

	/**
	 * search orders by orderId, managerId or senderId in different states (state
	 * -1:all 0:waiting 1:processing 2:finished)
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @param type
	 * @param search
	 * @param state
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/orderSearch", method = RequestMethod.POST)
	public String searchOrdersPOST(@RequestParam(value = "type") String type,
			@RequestParam(value = "search") String search,
			@RequestParam(value = "state", defaultValue = "-1") int state, Model model) {
		PaginationSupport<DeliveryOrder> paginationSupport;
		if (state == 0 || state == 1 || state == 2) {
			paginationSupport = deliveryOrderRepository.searchStatePage(1, 10, type, search, state);
		} else {
			state = -1;
			paginationSupport = deliveryOrderRepository.searchAllPage(1, 10, type, search);
		}
		model.addAttribute("search", search);
		model.addAttribute("type", type);
		model.addAttribute("state", state);
		model.addAttribute("paginationSupport", paginationSupport);
		return "manager/orders";
	}

	/**
	 * search orders by orderId, managerId or senderId in different states (state
	 * -1:all 0:waiting 1:processing 2:finished)
	 * 
	 * @param pageNo
	 * @param pageSize
	 * @param type
	 * @param search
	 * @param state
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/orderSearch", method = RequestMethod.GET)
	public String searchOrdersGET(@RequestParam(value = "state", defaultValue = "-1") int state,
			@RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
			@RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
			@RequestParam(value = "type") String type, @RequestParam(value = "search") String search, Model model) {
		PaginationSupport<DeliveryOrder> paginationSupport;
		if (state == 0 || state == 1 || state == 2) {
			paginationSupport = deliveryOrderRepository.searchStatePage(pageNo, pageSize, type, search, state);
		} else {
			state = -1;
			paginationSupport = deliveryOrderRepository.searchAllPage(pageNo, pageSize, type, search);
		}
		model.addAttribute("search", search);
		model.addAttribute("type", type);
		model.addAttribute("state", state);
		model.addAttribute("paginationSupport", paginationSupport);
		return "manager/orders";
	}

}
